import configparser
import chardet
from os import path


# import requests


class Config_Option:
    def __init__(self):
        """
        config配置操作，初始化ConfigParser实例
        """
        self.config = configparser.ConfigParser()

    # 读取指定的ini文件内容到ConfigParser实例中
    def read_ini_file(self, file_path):
        """
        读取指定的ini文件内容到ConfigParser实例中

        :param file_path: 要读取的ini文件的路径，字符串类型
        :return: 如果读取成功返回True，失败返回False（例如文件不存在等情况）
        """
        if path.exists(file_path):
            try:
                # self.config.read(file_path, encoding='utf-8')
                # return True
                with open(file_path, 'rb') as f:
                    rawdata = f.read()
                    result = chardet.detect(rawdata)
                    encoding = result['encoding']
                self.config.read(file_path, encoding=encoding)
            except configparser.Error as e:
                print(f"读取配置文件时出错: {e}")
                return False
        else:
            print(f"指定的文件 {file_path} 不存在")
            return False

    def read_ini_string(self, data):
        """
        读取INI格式的字符串内容到ConfigParser实例中

        :param data: 要读取的INI格式字符串，字符串类型
        :return: 如果读取成功返回True，失败返回False（例如格式错误等情况）
        """
        try:
            rawdata = data.encode()
            result = chardet.detect(rawdata)
            encoding = result['encoding']
            decoded_data = data.encode().decode(encoding)
            self.config.read_string(decoded_data)
            return True
        except configparser.Error as e:
            print(f"读取配置字符串时出错: {e}")
            return False

    # 创建新的ini文件
    def create_ini_file(self, file_path="", data=None):
        """
        创建新的ini文件

        :param file_path: 要创建的ini文件的路径，默认为空字符串。如果为空字符串，则创建一个空文件；
                          如果传入路径，则根据传入的数据创建对应的ini文件内容。
        :param data: 可选参数，期望传入的数据格式为字典嵌套结构，例如：
                     {
                         "section1": {
                             "key1": "value1",
                             "key2": "value2"
                         },
                         "section2": {
                             "key3": "value3"
                         }
                     }
                     如果不传此参数，则仅创建一个空文件。
        :return: 如果创建成功返回True，失败返回False（例如文件路径不可写等情况）
        """
        if file_path:
            try:
                if data:
                    self.config.read_dict(data)
                with open(file_path, 'w') as configfile:
                    self.config.write(configfile)
                return True
            except (IOError, configparser.Error) as e:
                print(f"创建配置文件时出错: {e}")
                return False
        else:
            try:
                # 创建一个空文件（仅创建，无实际内容）
                open('temp.ini', 'w').close()
                return True
            except IOError as e:
                print(f"创建临时空文件时出错: {e}")
                return False

    # 将当前ConfigParser实例中的配置数据保存到指定的ini文件中
    def save_ini_file(self, file_path):
        """
        将当前ConfigParser实例中的配置数据保存到指定的ini文件中

        :param file_path: 要保存的ini文件的路径，字符串类型
        :return: 如果保存成功返回True，失败返回False（例如文件不可写等情况）
        """
        try:
            with open(file_path, 'w', encoding='utf-8') as configfile:
                self.config.write(configfile)
            return True
        except IOError as e:
            print(f"保存配置文件时出错: {e}")
            return False

    # 列出ini文件中的所有section名称
    def list_sections(self):
        """
        列出ini文件中的所有section名称

        :return: 返回包含所有section名称的列表，如果没有section则返回空列表
        """
        return self.config.sections()

    # 修改指定的section名称
    def modify_section(self, old_section_name, new_section_name):
        """
        修改指定的section名称

        :param old_section_name: 原section名称
        :param new_section_name: 要修改成的新section名称
        :return: 如果修改成功返回True，失败返回False（例如原section不存在等情况）
        """
        if old_section_name in self.config.sections():
            items = self.config.items(old_section_name)
            self.config.remove_section(old_section_name)
            self.config.add_section(new_section_name)
            for key, value in items:
                self.config.set(new_section_name, key, value)
            return True
        return False

    # 删除指定的section，包括其下所有的options
    def delete_section(self, section_name):
        """
        删除指定的section，包括其下所有的options

        :param section_name: 要删除的section名称
        :return: 如果删除成功返回True，失败返回False（例如section不存在等情况）
        """
        if section_name in self.config.sections():
            self.config.remove_section(section_name)
            return True
        return False

    # 增加新的section
    def add_section(self, section_name):
        """
        增加新的section

        :param section_name: 要添加的新section名称
        :return: 如果添加成功返回True，失败返回False（例如section已存在等情况）
        """
        try:
            self.config.add_section(section_name)
            return True
        except configparser.DuplicateSectionError:
            return False

    # 列出指定section下的所有options（键名）
    def list_section_options(self, section_name):
        """
        列出指定section下的所有options（键名）

        :param section_name: 具体的section名称
        :return: 返回包含指定section下所有option键名的列表，如果section不存在或者没有options则返回空列表
        """
        if section_name in self.config.sections():
            return self.config.options(section_name)
        return []

    # 修改指定section的指定option名称或者值
    def modify_section_option(self, section_name, old_option_name, new_option_name, new_value=None):
        """
        修改指定section的指定option名称或者值

        :param section_name: 对应的section名称
        :param old_option_name: 原option名称
        :param new_option_name: 要修改成的新option名称（如果只修改值，可与原名称相同）
        :param new_value: 要修改成的新值，默认为None，若为None则只修改名称不修改值
        :return: 如果修改成功返回True，失败返回False（例如section或option不存在等情况）
        """
        if section_name in self.config.sections():
            if old_option_name in self.config.options(section_name):
                if new_value is None:
                    value = self.config.get(section_name, old_option_name)
                    self.config.remove_option(section_name, old_option_name)
                    self.config.set(section_name, new_option_name, value)
                else:
                    self.config.set(section_name, new_option_name, new_value)
                return True
        return False

    # 删除指定section下的指定option
    def delete_section_option(self, section_name, option_name):
        """
        删除指定section下的指定option

        :param section_name: 对应的section名称
        :param option_name: 要删除的option名称
        :return: 如果删除成功返回True，失败返回False（例如section不存在或者option不存在等情况）
        """
        if section_name in self.config.sections():
            if option_name in self.config.options(section_name):
                self.config.remove_option(section_name, option_name)
                return True
        return False

    # 增加指定section下的指定option
    def add_section_option(self, section_name, option_name, option_value):
        """
        增加指定section下的指定option

        :param section_name: 对应的section名称
        :param option_name: 要添加的option名称
        :param option_value: 要添加的option对应的取值
        :return: 如果添加成功返回True，失败返回False（例如section不存在等情况）
        """
        if section_name in self.config.sections():
            try:
                self.config.set(section_name, option_name, option_value)
                return True
            except configparser.NoSectionError:
                return False
        return False

    # 判断指定的section是否存在
    def section_exists(self, section_name):
        """
        判断指定的section是否存在

        :param section_name: 要判断的section名称
        :return: 如果存在返回True，否则返回False
        """
        return section_name in self.config.sections()

    # 判断指定section中的指定option是否存在
    def option_exists_in_section(self, section_name, option_name):
        """
        判断指定section中的指定option是否存在

        :param section_name: 对应的section名称
        :param option_name: 要判断的option名称
        :return: 如果存在返回True，否则返回False
        """
        if section_name in self.config.sections():
            return option_name in self.config.options(section_name)
        return False

    # 获取指定section中的指定option的值
    def get_section_option(self, section_name, option_name):
        """
        获取指定section中的指定option的值

        :param section_name: 对应的section名称
        :param option_name: 要获取值的option名称
        :return: 如果存在则返回对应的option值，否则返回None
        """
        if section_name in self.config.sections():
            if option_name in self.config.options(section_name):
                return self.config.get(section_name, option_name)
        return None

    # 列出所有section中的所有option，并整理成字典形式
    def list_all_options_as_dict(self):
        """
        列出所有section中的所有option，并整理成字典形式

        :return: 返回一个字典，外层键为section名称，内层键为对应section下的option名称，值为option的值，
                 如果没有section或者options则返回空字典
        """
        result_dict = {}
        for section in self.config.sections():
            result_dict[section] = dict(self.config.items(section))
        return result_dict
